/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.basic.hazard.source.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.basic.common.constant.enums.ParkBasicSysDictEnum;
import com.hopes.bizz.basic.gis.vo.hazard.HazLevelTotalVO;
import com.hopes.bizz.basic.gis.vo.hazard.HazLevelVO;
import com.hopes.bizz.basic.gis.vo.hazard.HazSensorClassifyVO;
import com.hopes.bizz.basic.gis.vo.hazard.HazVideoVO;
import com.hopes.bizz.basic.hazard.source.bo.HazHazardSourceOmDetailBO;
import com.hopes.bizz.basic.hazard.source.bo.HazMonitorFactorAndDataBO;
import com.hopes.bizz.basic.hazard.source.bo.HazStorageBO;
import com.hopes.bizz.basic.hazard.source.dto.HazHazardSourceExcelDTO;
import com.hopes.bizz.basic.hazard.source.entity.HazHazardSourceEntity;
import com.hopes.bizz.basic.hazard.source.entity.HazMonitorFactorEntity;
import com.hopes.bizz.basic.hazard.source.entity.HazStorageEntity;
import com.hopes.bizz.basic.hazard.source.mapper.HazHazardSourceMapper;
import com.hopes.bizz.basic.hazard.source.service.HazHazardSourceService;
import com.hopes.bizz.basic.hazard.source.service.HazMonitorFactorService;
import com.hopes.bizz.basic.hazard.source.service.HazStorageService;
import com.hopes.bizz.basic.hazard.source.vo.HazHazardSourceExcelVO;
import com.hopes.bizz.basic.hazard.source.vo.HazHazardSourceGisVO;
import com.hopes.bizz.basic.hazard.source.vo.HazHazardSourceOmDetailVO;
import com.hopes.bizz.basic.hazard.source.vo.HazHazardSourceOmVO;
import com.hopes.bizz.hazard.common.constant.enums.HazardModDictEnum;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.feign.RemoteCompanyService;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.common.core.constant.SecurityConstants;
import com.hopes.boss.common.core.util.R;
import com.hopes.boss.common.entity.ValidateImportBO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 重大危险源
 *
 * @author daijie
 * @date 2023-10-25 11:00:10
 */
@Service
@RequiredArgsConstructor
public class HazHazardSourceServiceImpl extends ServiceImpl<HazHazardSourceMapper, HazHazardSourceEntity> implements HazHazardSourceService {

    private final RemoteCompanyService remoteCompanyService;
    private final HazMonitorFactorService hazMonitorFactorService;
    private final HazStorageService hazStorageService;

    @Override
    public ValidateImportBO<HazHazardSourceExcelDTO> validateImport(List<HazHazardSourceExcelDTO> excelDTOList) {
        ValidateImportBO<HazHazardSourceExcelDTO> bo = new ValidateImportBO<>();
        List<ErrorMessage> errorMessageList = new ArrayList<>();
        List<HazHazardSourceExcelDTO> saveList = new ArrayList<>(excelDTOList);
        int successNum = excelDTOList.size();
        int failedNum = 0;

        bo.setErrorMessages(errorMessageList);
        bo.setSaveList(saveList);
        bo.setSuccessNum(successNum);
        bo.setFailedNum(failedNum);
        return bo;
    }

    @Override
    public HazHazardSourceEntity importDtoToEntity(HazHazardSourceExcelDTO excelDto) {
        HazHazardSourceEntity entity = new HazHazardSourceEntity();
        BeanUtils.copyProperties(excelDto, entity);
        return entity;
    }

    @Override
    public HazHazardSourceExcelVO exportEntityToVo(HazHazardSourceEntity entity) {
        HazHazardSourceExcelVO excelVO = new HazHazardSourceExcelVO();
        BeanUtils.copyProperties(entity, excelVO);
        excelVO.setChemicalProcess( DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.hazard_chemical_process, entity.getChemicalProcess()));
        return excelVO;
    }

    @Override
    public Page<?> getHazHazardSourceOmPage(Page page, HazHazardSourceEntity hazHazardSource) {
        LambdaQueryWrapper<HazHazardSourceEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjectUtils.isNotNull(hazHazardSource.getOrgId()), HazHazardSourceEntity::getOrgId, hazHazardSource.getOrgId());
        wrapper.eq(StringUtils.isNotBlank(hazHazardSource.getHazardSourceLevel()), HazHazardSourceEntity::getHazardSourceLevel, hazHazardSource.getHazardSourceLevel());
        wrapper.like(StringUtils.isNotBlank(hazHazardSource.getHazardName()), HazHazardSourceEntity::getHazardName, hazHazardSource.getHazardName());

        Page<HazHazardSourceEntity> entityPage = this.page(page, wrapper);
        List<HazHazardSourceOmVO> voList = new ArrayList<>();
        Page<HazHazardSourceOmVO> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal(), entityPage.searchCount());
        voPage.setRecords(voList);

        for (HazHazardSourceEntity record : entityPage.getRecords()) {
            HazHazardSourceOmVO vo = new HazHazardSourceOmVO();
            BeanUtils.copyProperties(record, vo);

            Long sourceId = record.getId();
            vo.setAlarmNum(hazMonitorFactorService.count(
                    Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                            .eq(HazMonitorFactorEntity::getAlarmOverStandard, true)));

            vo.setOnlineNum(hazMonitorFactorService.count(Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                    .eq(HazMonitorFactorEntity::getAlarmBrokenNet, false)));

            vo.setOfflineNum(hazMonitorFactorService.count(Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                    .eq(HazMonitorFactorEntity::getAlarmBrokenNet, true)));

            vo.setAlarmFlag(vo.getAlarmNum() > 0L);
            vo.setNetFlag(vo.getOfflineNum() > 0L);

            vo.setVideoNum(0);
            if (StringUtils.isNotBlank(vo.getVideoCodes())) {
                vo.setVideoNum(vo.getVideoCodes().split(StrUtil.COMMA).length);
            }

            voList.add(vo);
        }
        return voPage;
    }

    @Override
    public List<HazHazardSourceOmVO> gisOm() {
        List<HazHazardSourceEntity> list = this.list();
        List<HazHazardSourceOmVO> voList = new ArrayList<>();

        for (HazHazardSourceEntity record : list) {
            HazHazardSourceOmVO vo = new HazHazardSourceOmVO();
            BeanUtils.copyProperties(record, vo);

            Long sourceId = record.getId();
            vo.setAlarmNum(hazMonitorFactorService.count(
                    Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                            .eq(HazMonitorFactorEntity::getAlarmOverStandard, true)));

            vo.setOnlineNum(hazMonitorFactorService.count(Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                    .eq(HazMonitorFactorEntity::getAlarmBrokenNet, false)));

            vo.setOfflineNum(hazMonitorFactorService.count(Wrappers.<HazMonitorFactorEntity>lambdaQuery().eq(HazMonitorFactorEntity::getHazardSourceId, sourceId)
                    .eq(HazMonitorFactorEntity::getAlarmBrokenNet, true)));

            vo.setAlarmFlag(vo.getAlarmNum() > 0L);
            vo.setNetFlag(vo.getOfflineNum() > 0L);

            vo.setVideoNum(0);
            if (StringUtils.isNotBlank(vo.getVideoCodes())) {
                vo.setVideoNum(vo.getVideoCodes().split(StrUtil.COMMA).length);
            }

            voList.add(vo);
        }
        return voList;
    }

    @Override
    public HazHazardSourceOmDetailVO getOmById(Long id) {
        HazHazardSourceEntity entity = this.getById(id);
        HazHazardSourceOmDetailVO result = new HazHazardSourceOmDetailVO();
        BeanUtils.copyProperties(entity, result);

        result.setVideoNum(0);
        if (StringUtils.isNotBlank(result.getVideoCodes())) {
            result.setVideoNum(result.getVideoCodes().split(",").length);
        }

        Map<Long, List<HazMonitorFactorEntity>> factorMap = hazMonitorFactorService.list(Wrappers.<HazMonitorFactorEntity>lambdaQuery()
                .eq(HazMonitorFactorEntity::getHazardSourceId, id)).stream().collect(Collectors.groupingBy(HazMonitorFactorEntity::getFactorId));
        List<HazHazardSourceOmDetailBO> boList = new ArrayList<>();
        result.setHazHazardSourceOmDetailBOList(boList);

        for (Long key : factorMap.keySet()) {
            HazHazardSourceOmDetailBO bo = new HazHazardSourceOmDetailBO();
            bo.setFactorId(key);
            bo.setFactorName(DictResolver.getItemLabelByValue(HazardModDictEnum.factor_config, key));
            bo.setFactorNum(factorMap.get(key).size());

            boList.add(bo);
        }

        List<HazStorageEntity> storageList = hazStorageService.list(Wrappers.<HazStorageEntity>lambdaQuery()
                .eq(HazStorageEntity::getHazardSourceId, id));

        List<HazStorageBO> hazStorageBOList = new ArrayList<>();
        for (HazStorageEntity hazStorageEntity : storageList) {
            HazStorageBO bo = new HazStorageBO();
            BeanUtils.copyProperties(hazStorageEntity, bo);

            HazMonitorFactorEntity factorParam = new HazMonitorFactorAndDataBO();
            factorParam.setHazardSourceId(id);
            factorParam.setStorageId(bo.getId());
            bo.setHazMonitorFactorList(hazMonitorFactorService.getAllFactorAndData(factorParam));
            hazStorageBOList.add(bo);
        }

        result.setHazStorageList(hazStorageBOList);
        return result;
    }

    @Override
    public HazHazardSourceGisVO getHazardSourceLevel() {
        HazHazardSourceGisVO hazHazardSourceGisVO = new HazHazardSourceGisVO();
        JSONArray pieData = new JSONArray();
        List<HazHazardSourceEntity> hazHazardSourceEntities = baseMapper.selectList(null);
        // 重大危险源等级统计
        Map<String, Long> hazSource = hazHazardSourceEntities.stream().collect(Collectors.groupingBy(HazHazardSourceEntity::getHazardSourceLevel, Collectors.counting()));
        hazHazardSourceGisVO.setHazardSourceCount(hazHazardSourceEntities.size());
        hazHazardSourceGisVO.setPieCount(pieData);
        hazSource.forEach((k,v)->{
            JSONObject data = new JSONObject();
            data.put("name",DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.haz_hazard_source_level,k));
            data.put("value",v);
            pieData.add(data);
        });

        return hazHazardSourceGisVO;
    }

    @Override
    public HazLevelTotalVO hazardSourceLevelCount() {
        final List<HazLevelVO> hazLevelVOList = new ArrayList<>();
        final List<HazHazardSourceEntity> hazHazardSourceList = baseMapper.selectList(null);
        // 重大危险源等级统计
        final Map<String, Long> hazSourceLevelMap = hazHazardSourceList.stream().collect(Collectors.groupingBy(HazHazardSourceEntity::getHazardSourceLevel, Collectors.counting()));
        final List<SysDictItem> itemsByTypeList = DictResolver.getItemsByType(ParkBasicSysDictEnum.haz_hazard_source_level);
        for (SysDictItem sysDictItem : itemsByTypeList) {
            final HazLevelVO hazLevelVO = new HazLevelVO(sysDictItem.getCode(), MapUtil.getInt(hazSourceLevelMap, sysDictItem.getCode(), 0));
            hazLevelVOList.add(hazLevelVO);
        }
        return new HazLevelTotalVO(hazLevelVOList);
    }

    @Override
    public List<HazSensorClassifyVO> hazardSensorClassifyCount() {
        final List<HazSensorClassifyVO> hazSensorClassifyList = new ArrayList<>();
        final LambdaQueryWrapper<HazMonitorFactorEntity> wrapper = Wrappers.<HazMonitorFactorEntity>lambdaQuery().select(HazMonitorFactorEntity::getId, HazMonitorFactorEntity::getFactorId, HazMonitorFactorEntity::getFactorName);
        final List<HazMonitorFactorEntity> monitorFactorList = hazMonitorFactorService.list(wrapper);
        final Map<Long, Long> longMap = monitorFactorList.stream().filter(e -> ObjUtil.isNotNull(e.getFactorId())).collect(Collectors.groupingBy(HazMonitorFactorEntity::getFactorId, Collectors.counting()));
        final Map<Long, String> longStringMap = monitorFactorList.stream().filter(e -> ObjUtil.isNotNull(e.getFactorId())).collect(Collectors.toMap(HazMonitorFactorEntity::getFactorId, HazMonitorFactorEntity::getFactorName));

        for (Map.Entry<Long, Long> entry : longMap.entrySet()) {
            final Long key = entry.getKey();
            final HazSensorClassifyVO hazSensorClassifyVO = new HazSensorClassifyVO(key, entry.getValue().intValue(), MapUtil.getStr(longStringMap, key));
            hazSensorClassifyList.add(hazSensorClassifyVO);
        }
        return hazSensorClassifyList;
    }

    @Override
    public HazVideoVO hazardVideoNumberCount() {
        // 企业数量
        final Integer companyNum = Optional.ofNullable(remoteCompanyService.count(SecurityConstants.FROM_IN)).map(R::getData).map(Long::intValue).orElse(0);
        // 危险源数量
        final List<HazHazardSourceEntity> hazHazardSourceList = getBaseMapper().selectList(
                Wrappers.<HazHazardSourceEntity>lambdaQuery().select(HazHazardSourceEntity::getId, HazHazardSourceEntity::getVideoCodes));
        // 危险源视频数量
        final int hazSourceVideoNum = Long.valueOf(hazHazardSourceList.stream().map(HazHazardSourceEntity::getVideoCodes).filter(StrUtil::isNotEmpty).count()).intValue();
        // 视频编码
        final List<String> videoCodeList = hazHazardSourceList.stream().map(HazHazardSourceEntity::getVideoCodes).filter(StrUtil::isNotEmpty).collect(Collectors.toList());
        return new HazVideoVO(companyNum, hazHazardSourceList.size(), hazSourceVideoNum, videoCodeList.size() < 2 ? videoCodeList : videoCodeList.subList(0, 2));
    }

    //    @Override
//    public HazHazardSourceOmDetailVO getOmById(Long id) {
//        HazHazardSourceEntity entity = this.getById(id);
//        HazHazardSourceOmDetailVO result = new HazHazardSourceOmDetailVO();
//        BeanUtils.copyProperties(entity, result);
//
//        result.setVideoNum(0);
//        if (StringUtils.isNotBlank(result.getVideoCodes())) {
//            result.setVideoNum(result.getVideoCodes().split(",").length);
//        }
//
//        Map<Long, List<HazMonitorFactorEntity>> factorMap = hazMonitorFactorService.list(Wrappers.<HazMonitorFactorEntity>lambdaQuery()
//                .eq(HazMonitorFactorEntity::getHazardSourceId, id)).stream().collect(Collectors.groupingBy(HazMonitorFactorEntity::getFactorId));
//        List<HazHazardSourceOmDetailBO> boList = new ArrayList<>();
//        result.setHazHazardSourceOmDetailBOList(boList);
//
//        for (Long key : factorMap.keySet()) {
//            HazHazardSourceOmDetailBO bo = new HazHazardSourceOmDetailBO();
//            bo.setFactorId(key);
//            bo.setFactorName(DictResolver.getItemLabelByValue(HazardModDictEnum.factor_config, key));
//            bo.setFactorNum(factorMap.get(key).size());
//
//            boList.add(bo);
//        }
//
//        List<Long> storageIds = hazMonitorFactorService.list(Wrappers.<HazMonitorFactorEntity>lambdaQuery()
//                .eq(HazMonitorFactorEntity::getHazardSourceId, id)).stream().map(HazMonitorFactorEntity::getStorageId).collect(Collectors.toList());
//        List<BasicStorageEntity> storageEntities = remoteBasicStorageService.getList(SecurityConstants.FROM).getData();
//        List<BasicStorageEntity> storageList = storageEntities.stream().filter(it -> storageIds.contains(it.getId())).collect(Collectors.toList());
//
//        List<HazStorageBO> hazStorageBOList = new ArrayList<>();
//        for (BasicStorageEntity hazStorageEntity : storageList) {
//            HazStorageBO bo = new HazStorageBO();
//            BeanUtils.copyProperties(hazStorageEntity, bo);
//
//            HazMonitorFactorEntity factorParam = new HazMonitorFactorAndDataBO();
//            factorParam.setHazardSourceId(id);
//            factorParam.setStorageId(bo.getId());
//            bo.setHazMonitorFactorList(hazMonitorFactorService.getAllFactorAndData(factorParam));
//            hazStorageBOList.add(bo);
//        }
//
//        result.setHazStorageList(hazStorageBOList);
//        return result;
//    }
}
